package cn.anc.httpcontrolutil;

import android.app.Activity;
import android.text.TextUtils;
import android.util.Log;

import org.json.JSONObject;

import java.io.File;
import java.io.IOException;

import androidx.annotation.Nullable;
import cn.anc.aonicardv.util.EncrytUtils;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;

/**
 * Created by baobaoding on 2017/5/6.
 */

public class HttpFileUpload extends Thread {
    private static String TAG = HttpFileUpload.class.getSimpleName();
    private OkHttpClient mOkHttpClient = new OkHttpClient();
    private String upload_url = null;
    private String upload_key = null;
    private String local_path = null;
    private HttpFileUploadListener listener = null;
    private Activity activity = null;
    private String localMd5;

    public interface HttpFileUploadListener {
        void OnEvent(int eventCode, HttpFileUploadResult result);

        void OnUploadProgress(int progress);
    }

    private void guiOnEvent(final int eventCode, final HttpFileUploadResult result) {
        if (listener != null && activity != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    listener.OnEvent(eventCode, result);
                }
            });
        }
    }

    private void guiOnProgress(final int progress) {
        if (listener != null && activity != null) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    listener.OnUploadProgress(progress);
                }
            });
        }
    }

    public static class HttpFileUploadEvent {
        public static final int HTTP_FILE_UPLOAD_START = 0;
        public static final int HTTP_FILE_UPLOAD_SUCCESS = 1;
        public static final int HTTP_FILE_UPLOAD_FAIL = 2;
    }

    public class HttpFileUploadResult {
        public int rval = -1;
        public String video_url = null;
        public String thumb_url = null;
        public String md5 = null;
    }

    public HttpFileUpload(Activity _activity, String _upload_url, String _upload_key, String _local_path) {
        activity = _activity;
        upload_url = _upload_url;
        upload_key = _upload_key;
        local_path = _local_path;
    }

    public HttpFileUpload(Activity _activity, String _upload_url, String _upload_key, String _local_path, HttpFileUploadListener _listener) {
        activity = _activity;
        upload_url = _upload_url;
        upload_key = _upload_key;
        local_path = _local_path;
        listener = _listener;
    }

    @Override
    public void run() {
        super.run();
        try {
            localMd5 = EncrytUtils.getMd5ByFile(new File(local_path));
            File file = new File(local_path);
            String filename = file.getName();
            guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_START, null);
            ProgressRequestBody progressRequestBody = new ProgressRequestBody(MediaType.parse("application/octet-stream"), file);
            RequestBody body = new MultipartBody
                    .Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart(upload_key, filename, progressRequestBody)
                    .build();
            Request request = new Request.Builder().url(upload_url).post(body).build();
            Response response = mOkHttpClient.newCall(request).execute();
            Log.d(TAG, "upload code:" + response.code());
            if (response == null || response.code() != 200) {
                if (response != null) {
                    Log.d(TAG, "upload code:" + response.code());
                }
                guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_FAIL, null);
                return;
            }
            Log.d(TAG, "upload: ok");
            fileUploadOkHandler(response, listener);
        } catch (Exception ex) {
            Log.e(TAG, "upload: " + ex.getMessage());
            guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_FAIL, null);
        }
    }

    private void fileUploadOkHandler(Response response, HttpFileUploadListener listener) {
        if (listener != null) {
            try {
                HttpFileUploadResult result = new HttpFileUploadResult();
                JSONObject obj = new JSONObject(response.body().string());
                Log.w(TAG, "onResponse: ----obj:" + obj);
                if (obj.has("rval")) {
                    result.rval = obj.getInt("rval");
                }
                if (obj.has("path")) {
                    result.video_url = obj.getString("path");
                }
                if (obj.has("thumb")) {
                    result.thumb_url = obj.getString("thumb");
                }
                if (obj.has("md5")) {
                    result.md5 = obj.getString("md5");
                }
                if (!TextUtils.isEmpty(localMd5) &&!TextUtils.isEmpty(result.md5) && localMd5.equalsIgnoreCase(result.md5))
                    guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_SUCCESS, result);
                else
                    guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_FAIL, null);
            } catch (Exception ex) {
                Log.w(TAG, "onResponse: " + ex.getMessage());
                guiOnEvent(HttpFileUploadEvent.HTTP_FILE_UPLOAD_FAIL, null);
            }
        }
    }

    private class ProgressRequestBody extends RequestBody {
        private MediaType mediaType = null;
        private File file = null;

        public ProgressRequestBody(MediaType _mediatype, File _file) {
            this.mediaType = _mediatype;
            this.file = _file;
        }

        @Nullable
        @Override
        public MediaType contentType() {
            return mediaType;
        }

        @Override
        public long contentLength() throws IOException {
            return file.length();
        }

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            Source source = Okio.source(file);
            sink.writeAll(source);
            /*Buffer buf = new Buffer();
            long totalBytes = contentLength();
            long writeBytes = 0;
            for (long readCount; (readCount = source.read(buf, 8192)) != -1;) {
                sink.write(buf, readCount);
                writeBytes += readCount;
                Log.e(TAG, "writeBytes4: " + writeBytes + ",progress:" + (writeBytes * 100) / totalBytes);
                //listener.onProgress(contentLength(), remaining -= readCount, remaining == 0);
            }*/
        }
    }
}
